home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
microcrn
/
issue_49.arc
/
6805DEMO.ARC
/
EXAMPLE.ASM
Wrap
Assembly Source File
|
1989-07-11
|
13KB
|
364 lines
* Micro Cornucopia Magazine Issue #49
* 6805 Controller Example Project Code
*
* EXAMPLE.ASM
*
* Sample program showing design of control program, to be run from
* the EPROM of an MC68HC705 MCU. The program monitors one channel
* of A/D, using an MC145041 Serial A/D converter chip. LEDs are
* sequenced as needed, depending on the value of the A/D channel.
*
* The A/D chip connects to the MCU through the Serial Peripheral
* Interface (SPI). The chip select line for the A/D is bit 3 of MCU
* Port C; a low on this line selects the A/D chip.
*
* Three status LEDs connect to bits 0-2 of MCU port C. LED1 (port C,
* bit 0) stays on at all times, to show the program is actually running.
* LED2 (port C, bit 1) stays on at all times, provided the A/D value
* stays below $40. If the value rises to between $40 and $7F, LED2
* blinks once per second. If the value rises above $7F, LED2 goes out.
* LED3 (port C, bit 2) only comes on if the A/D value reaches $80.
* If the value lies between $80 and $BF, LED3 stays on. If the value
* rises above $BF, LED3 blinks once per second.
*
* The code for routine TIME and much of the code in MAIN comes directly
* from the example development project in the M68HC05 Microcontroller
* Applications Guide. Refer to pages 4-24 for the original listing.
* The same program is provided by Motorola as Freeware and as source
* code on the program disc that accompanies the Applications Guide.
* I would give credit to the original programmer, if I knew who he/she
* was.
*
*
* Register equates
*
PORTA EQU $00 Port A data register
PORTB EQU $01 Port B data register
PORTC EQU $02 Port C data register
PORTD EQU $03 Port D data register
DDRA EQU $04 Data direction, Port A
DDRB EQU $05 Data direction, Port B
DDRC EQU $06 Data direction, Port C
SPCR EQU $0A SPIE,SPE,-,MSTR;CPOL,CPHA,SPR1,SPR0
SPSR EQU $0B SPIF,WCOL,-,MODF;-,-,-,-
SPDR EQU $0C SPI Data
BAUD EQU $0D -,-,SCP1,SCP0;-,SCR2,SCR1,SCR0
SCCR1 EQU $0E R8,T8,-,M;WAKE,-,-,-
SCCR2 EQU $0F TIE,TCIE,RIE,ILIE;TE,RE,RWU,SBK
SCSR EQU $10 TDRE,TC,RDRF,IDLE;OR,NF,FE,-
SCDR EQU $11 SCI Data
RDR EQU $11 SCI Receive Data (same as SCDR)
TDR EQU $11 SCI Transmit Data (same as SCDR)
TCR EQU $12 ICIE,OCIE,TOIE,0;0,0,IEGE,OLVL
TSR EQU $13 ICF,OCF,TOF,0; 0,0,0,0
ICAP EQU $14 Input Capture Reg (Hi-$14, Lo-$15)
OCMP EQU $16 Output Compare Reg (Hi-$16, Lo-$17)
TCNT EQU $18 Timer Count Reg (Hi-$18, Lo-$19)
ALTCNT EQU $1A Alternate Count Reg (Hi-$1A, Lo-$1B)
*
* Following equates are timer values to produce a 50 msec delay
* using the MCU timing registers. Use ONLY one pair of values,
* depending on the MCU timing crystal for the target system.
*
TMRCNTL EQU $D4 FOR 2.0 MHZ CLOCK
TMRCNTH EQU $30
* TMRCNTL EQU $6A FOR 1.0 MHZ CLOCK
* TMRCNTH EQU $18
ORG $50 START OF VARIABLES IN RAM
TEMPA RMB 1 TEMP STORAGE FOR ACC
TEMPX RMB 1 TEMP STORAGE FOR XR
TIC RMB 1 50 MSEC TICS; 0-19, 20 TICS = 1 SEC
SEC RMB 1 CURRENT TIME IN SECONDS
MIN RMB 1 CURRENT TIME IN MINUTES
HR RMB 1 CURRENT TIME IN HOURS
AMPM RMB 1 CURRENT TIME (0 = AM, 1 = PM)
DAY RMB 1 CURRENT DAY (1 = SUN...7 = SAT)
LED1 RMB 1 CONTROL BYTE FOR LED1 (0 = DARK)
LED2 RMB 1 CONTROL BYTE FOR LED2 (0 = DARK)
LED3 RMB 1 CONTROL BYTE FOR LED3 (0 = DARK)
ORG $0100 START OF PROGRAM IN ROM
INIT RSP INITIALIZE THE STACK POINTER
*
* Set timer and SPI characteristics.
*
LDA #$50 SPI: MCU IS MASTER, 2 USEC CLOCK
STA SPCR WRITE TO SPI CONTROL REG
CLRA TIMER: NO INTERRUPTS OR PINS USED
STA TCR WRITE TO TIMER CONTROL REG
*
* Set up port C, bits 0-2 for output as LED controllers.
* Clear LED control bytes (turns LEDs off later).
*
* Set up port C, bit 3 for output as A/D chip select.
*
LDA #$0F BITS 0-3 = OUTPUT, ALL OTHERS = INPUT
STA DDRC SETUP PORT C
CLR LED1 SHOW ALL LEDS AS OFF
CLR LED2
CLR LED3
*
* Initialize clock to show 12:00 AM Sunday.
*
CLR TIC ZERO THE TIC COUNTER
CLR SEC SET SECONDS TO 0
LDA #12 SET HOUR TO NOON
STA HR
CLR MIN SET MINUTES TO 0
CLR AMPM SET TO MORNING
LDA #1 SET DAY TO SUNDAY
STA DAY
*
* ----- END OF INITIALIZATION -----
*
*
* MAIN
*
* This loop gets executed once each 50 msec, based on the
* MCU's internal timer. The compare register is loaded
* with a target value. When the timer hits that value,
* bit 6 of the Output Compare Register (OCR) gets set,
* marking the end of a 50 msec interval.
*
* At each interval, the timer is reloaded, the time/day clock
* is updated, and the chain of subroutines at the bottom of
* the loop is executed. So long as the chain takes no more
* than 50 msec to complete, the MCU will stay on-time.
*
MAIN EQU *
BRCLR 6,TSR,MAIN LOOP HERE UNTIL TIME OUT
LDA OCMP+1 LOW BYTE OF OCR
ADD #TMRCNTL CALCULATE NEW TIMER TARGET
STA TEMPA
LDA OCMP DO BOTH HALVES OF 16-BIT VALUE
ADC #TMRCNTH
STA OCMP
LDA TEMPA
STA OCMP+1 TIMER TARGET RELOADED
LDA TIC GET TIC COUNTER
INCA BUMP IT
STA TIC AND SAVE NEW VALUE
CMP #20 DONE ONE SECOND YET?
BLO ARNC1 IF NOT, DON'T CLEAR TIC
CLR TIC YES, START A NEW SECOND
ARNC1 EQU *
*
* End of the timing loop; following chain of subroutine calls
* must complete within 50 msecs.
*
JSR TIME UPDATE TIME-OF-DAY CLOCK
JSR PROCESS READ A/D, SET LED CONTROL BYTES
JSR LEDS PROCESS PENDING LED COMMANDS
BRA MAIN DO IT ALL AGAIN
*
* TIME
*
* Update the time-of-day clock.
*
TIME EQU *
TST TIC Check for TIC=zero
BNE XTIME If not; just exit
INC SEC SEC=SEC+1
LDA #60
CMP SEC Did SEC -> 60 ?
BNE XTIME If not; just exit
CLR SEC Seconds rollover
INC MIN MIN=MIN+1
CMP MIN A still 60; MIN=60 ?
BNE XTIME If not; just exit
CLR MIN Minutes rollover
INC HR HR=HR+1
LDA HR For comparisons
CMP #13 HR=13 ?
BNE ARNS1 If not; skip
LDA #1
STA HR Set HR=1
BRA XTIME Exit
ARNS1 CMP #12 HR=12 ?
BNE XTIME If not; just exit
LDA AMPM
EOR #%00000001 Invert AM/PM bit
STA AMPM 0=AM, 1=PM
BNE XTIME If not AM now; just exit
INC DAY DAY=DAY+1
LDA DAY
CMP #8 Day rollover ?
BNE XTIME If not; just exit
LDA #1
STA DAY Set Day to 1 (SUN)
XTIME RTS
*
* LEDS -- Process any pending LED commands, based on the LED
* control bytes.
*
* Each LED control byte determines whether an LED is turned on
* or off. If the byte is 0, that LED is always turned off by this
* routine. If the byte is not 0, the corresponding LED is always
* turned on and the control byte is decremented.
*
* If this routine is called each slice (20 times per second), the
* longest period of time an LED can remain lit without intervention
* is 255 * 50 msec = 12750 msec or 12.75 seconds.
*
LEDS TST LED1 NEED TO TURN ON LED1?
BEQ LED1N BRANCH IF TIME TO TURN OFF
BCLR 0,PORTC TURN ON LED1 (ACTIVE LOW)
DEC LED1 COUNT THIS 50 MSEC
BRA LED2T GO TEST LED2
LED1N BSET 0,PORTC TURN OFF LED1
LED2T TST LED2 DO IT AGAIN FOR LED2
BEQ LED2N
BCLR 1,PORTC USE BIT 1 FOR LED2
DEC LED2
BRA LED3T
LED2N BSET 1,PORTC
LED3T TST LED3 SAME AGAIN FOR LED3
BEQ LED3N
BCLR 2,PORTC USE BIT 2 FOR LED3
DEC LED3
BRA LEDSX
LED3N BSET 2,PORTC
LEDSX RTS
*
* PROCESS -- Change LED control bytes as needed to reflect current
* status of A/D input.
*
* If TIC holds a 0 (first 50 msec slice of each second), read channel
* 0 of the A/D and trash the returned value.
*
* If TIC holds a 1 (second 50 msec slice of each second), read
* channel 0 of the A/D and process the LED states, depending on the
* following:
*
* Value range Action taken
* ----------- --------------------------------------------
*
* $00 - $3F Turn LED2 on for one second, turn LED3 off.
* $40 - $7F Turn LED2 on for .5 seconds, turn LED3 off.
* $80 - $BF Turn LED2 off, turn LED3 on for one second.
* $C0 - $FF Turn LED2 off, turn LED3 on for .5 seconds.
*
* All other values of TIC are ignored by this routine. Note
* that LED1 is always on.
*
PROCESS
LDA #$FF GET LONGEST ON-TIME
STA LED1 ALWAYS LEAVE LED1 ON
LDA TIC GET CURRENT TIC VALUE
BNE PROCS1 BRANCH IF NOT FIRST TIC
BSR A2D LOAD UP CHANNEL 0 VALUE
BRA PROCSX AND LEAVE
PROCS1 CMP #1 IS THIS THE SECOND TIC?
BNE PROCSX BRANCH IF NOT
CLRA LOAD UP CHANNEL 0 AGAIN
BSR A2D AND READ THAT CHANNEL
CMP #$40 IS VALUE IN GOOD RANGE?
BHS PROCS2 BRANCH IF NOT
CLR LED3 TURN OFF LED3
LDA #20 TURN ON LED2 FOR 1 SECOND
STA LED2
BRA PROCSX AND LEAVE
PROCS2 CMP #$80 IS VALUE IN FAIR RANGE?
BHS PROCS3 BRANCH IF NOT
CLR LED3 TURN OFF LED3
LDA #10 TURN ON LED2 FOR .5 SECONDS
STA LED2
BRA PROCSX AND LEAVE
PROCS3 CMP #$C0 IS VALUE IN POOR RANGE?
BHS PROCS4 BRANCH IF NOT
CLR LED2 TURN OFF LED2
LDA #20 TURN ON LED3 FOR 1 SECOND
STA LED3
BRA PROCSX AND LEAVE
PROCS4 CLR LED2 MUST BE BAD, SHUT OFF LED2
LDA #10 TURN ON LED3 FOR .5 SECONDS
STA LED3
PROCSX RTS
*
* A2D -- Read selected channel of serial A/D (MC145041).
*
* Enter with A/D channel number in ACC. Returns analog value
* in ACC. Assumes chip select line to A/D chip is driven by
* port C, bit 3 (active low).
*
* Note that the value returned by A2D corresponds to the most
* recent previous channel number transmitted, not the current
* channel number! Therefore, unless you know for a fact that
* the last channel number you sent was the one you want to read
* now, you had better call this routine twice, using the same
* channel number.
*
A2D
TST SPSR CLEAR SPIF
BCLR 3,PORTC PULL CHIP SELECT LINE LOW
ASLA MOVE CHANNEL NUMBER TO HIGH NYBBLE
ASLA
ASLA
ASLA
STA SPDR SEND CHANNEL TO SPI
SPIFLP BRCLR 7,SPSR,SPIFLP WAIT UNTIL COMPLETE
BSET 3,PORTC RELEASE CHIP SELECT
LDA SPDR GET VALUE RETURNED
RTS
*
* Set up the RESET vector. This is required for code that will
* be moved into the MCU's EPROM for later execution.
*
ORG $1FFE RESET VECTOR
FDB INIT POINT TO START OF PROGRAM